﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;

namespace Apewer
{

    /// <summary>集合的实用工具。</summary>
    public static class CollectionUtility
    {

        #region 判断

        /// <summary>判断集合为空。</summary>
        public static bool IsEmpty<T>(IEnumerable<T> objects)
        {
            if (objects == null) return true;
            if (objects is T[]) return ((T[])objects).LongLength < 1L;
            if (objects is ICollection<T>) return ((ICollection<T>)objects).Count < 1;
            foreach (var item in objects) return false;
            return true;
        }

        /// <summary>判断集合存在元素。</summary>
        public static bool NotEmpty<T>(IEnumerable<T> objects)
        {
            if (objects == null) return false;
            if (objects is T[]) return ((T[])objects).LongLength > 0L;
            if (objects is ICollection<T>) return ((ICollection<T>)objects).Count > 0;
            foreach (var item in objects) return true;
            return false;
        }

        /// <summary>获取集合中元素的数量。</summary>
        public static int Count<T>(IEnumerable<T> objects)
        {
            if (objects == null) return 0;

            var array = objects as T[];
            if (array != null) return array.Length;

            var collection = objects as ICollection<T>;
            if (collection != null) return collection.Count;

            var count = 0;
            foreach (var cell in objects) count++;
            return count;
        }

        /// <summary>检查集合是否包含 item。</summary>
        public static bool Contains<T>(IEnumerable<T> objects, T cell)
        {
            if (objects == null) return false;

            // objects 实现了含有 Contains 方法的接口。
            if (objects is ICollection<T>) return ((ICollection<T>)objects).Contains(cell);

            // cell 无效。
            if (cell == null)
            {
                foreach (var i in objects)
                {
                    if (i == null) return true;
                }
                return false;
            }

            // cell 有效，进行默认比较。
            var comparer = EqualityComparer<T>.Default;
            foreach (var i in objects)
            {
                if (comparer.Equals(i, cell)) return true;
            }
            return false;
        }

        /// <summary>获取 item 在集合中的偏移位置，不存在时返回 -1。</summary>
        public static int IndexOf<T>(IEnumerable<T> objects, T item)
        {
            if (objects == null) return -1;
            if (objects is IList list) return list.IndexOf(item);

            if (item == null)
            {
                if (objects is T[] array)
                {
                    var length = array.Length;
                    for (var i = 0; i < length; i++)
                    {
                        if (array[i] == null) return i;
                    }
                    return -1;
                }

                var index = 0;
                foreach (var obj in objects)
                {
                    if (obj == null) return index;
                    index++;
                }
                return -1;
            }
            else
            {
                var comparer = EqualityComparer<T>.Default;

                if (objects is T[] array)
                {
                    var length = array.Length;
                    for (var i = 0; i < length; i++)
                    {
                        if (comparer.Equals(item, array[i])) return i;
                    }
                    return -1;
                }

                var index = 0;
                foreach (var obj in objects)
                {
                    if (comparer.Equals(item, obj)) return index;
                    index++;
                }
                return -1;
            }
        }

        #endregion

        #region 类型转换

        /// <summary>转换模型类型。</summary>
        public static TDst[] As<TSrc, TDst>(this TSrc[] array) where TDst : class
        {
            if (array == null) return null;
            var count = array.Length;
            var output = new TDst[count];
            for (var i = 0; i < count; i++)
            {
                var item = array[i];
                if (item == null) continue;
                output[i] = item as TDst;
            }
            return output;
        }

        /// <summary>转换模型类型。</summary>
        public static TDst[] As<TSrc, TDst>(this TSrc[] array, Func<TSrc, TDst> convert)
        {
            if (convert == null) throw new ArgumentNullException(nameof(convert));

            if (array == null) return null;
            var count = array.Length;
            var output = new TDst[count];
            for (var i = 0; i < count; i++)
            {
                var item = array[i];
                if (item == null) continue;
                output[i] = convert(item);
            }
            return output;
        }

        /// <summary>安全转换为 List&lt;<typeparamref name="T"/>&gt; 对象。可指定排除 NULL 值元素。</summary>
        public static List<T> List<T>(IEnumerable<T> objects, bool excludeNull = false)
        {
            if (objects == null) return new List<T>();

            var list = new List<T>();
            var collection = objects as ICollection;
            if (collection != null)
            {
                list.AddRange(objects);
            }
            else
            {
                var group = 1024;
                var added = 0;
                var capacity = 0;
                if (objects != null)
                {
                    foreach (var item in objects)
                    {
                        if (excludeNull && item == null) continue;
                        if (added == capacity)
                        {
                            capacity += group;
                            list.Capacity = capacity;
                        }
                        list.Add(item);
                        added += 1;
                    }
                }
                list.Capacity = added;
            }
            return list;
        }

        /// <summary>安全转换为 &lt;<typeparamref name="T"/>&gt;[] 对象。可指定排除 NULL 值元素。</summary>
        public static T[] Array<T>(IEnumerable<T> objects, bool excludeNull = false)
        {
            if (objects == null) return new T[0];
            if (objects is T[]) return (T[])objects;

            var collection = objects as ICollection;
            if (collection != null)
            {
                var array = new T[collection.Count];
                collection.CopyTo(array, 0);
                return array;
            }
            else
            {
                var group = 1024;
                var array = new T[group];
                var added = 0;
                var capacity = 0;
                foreach (var item in objects)
                {
                    if (excludeNull && item == null) continue;
                    if (added == capacity)
                    {
                        capacity += group;
                        var temp = new T[capacity];
                        System.Array.Copy(array, 0, temp, 0, added);
                        array = temp;
                    }
                    array[added] = item;
                    added += 1;
                }
                if (added < 1 || added == capacity) return array;
                var collapsed = new T[added];
                System.Array.Copy(array, 0, collapsed, 0, added);
                return collapsed;
            }
        }

        /// <summary>生成 StringPairs 对象实例为副本。</summary>
        public static StringPairs StringPairs(NameValueCollection @this) => Apewer.StringPairs.From(@this);

        /// <summary>转换集合为数组。</summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static Dictionary<string, string[]> Dictionary(NameValueCollection collection)
        {
            if (collection == null) return null;
            var count = collection.Count;
            var dict = new Dictionary<string, string[]>();
            for (var i = 0; i < count; i++)
            {
                var key = collection.GetKey(i);
                var values = collection.GetValues(i);
                dict.Add(key, values);
            }
            return dict;
        }

        /// <summary>转换集合为字典。</summary>
        /// <typeparam name="TKey">字典 Key 的类型。</typeparam>
        /// <typeparam name="TValue">字典 Value 的类型。</typeparam>
        /// <param name="items">要转换的集合。</param>
        /// <param name="key">根据元素获取 Key 的函数。</param>
        /// <exception cref="ArgumentNullException"></exception>
        public static Dictionary<TKey, TValue> Dictionary<TKey, TValue>(IEnumerable<TValue> items, Func<TValue, TKey> key)
        {
            if (items == null) throw new ArgumentNullException(nameof(items));
            if (key == null) throw new ArgumentNullException(nameof(key));

            var dict = new Dictionary<TKey, TValue>();
            foreach (var i in items)
            {
                if (i == null) continue;

                var k = key(i);
                if (k.IsNull()) continue;
                if (dict.ContainsKey(k)) continue;
                dict.Add(k, i);
            }
            return dict;
        }

        #endregion

        #region 修改集合

        /// <summary>添加多个元素。</summary>
        public static void Add<T>(List<T> list, params T[] items)
        {
            if (list != null && items != null) list.AddRange(items);
        }

        /// <summary>添加多个元素。</summary>
        public static IList<T> Add<T>(IList<T> list, IEnumerable<T> items)
        {
            if (list != null && items != null)
            {
                foreach (var item in items) list.Add(item);
            }
            return list;
        }

        /// <summary>添加元素。</summary>
        public static bool Add<TKey, TValue>(IList<KeyValuePair<TKey, TValue>> list, TKey key, TValue value)
        {
            if (list == null) return false;
            list.Add(new KeyValuePair<TKey, TValue>(key, value));
            return true;
        }

        /// <summary>对元素去重，且去除 NULL 值。</summary>
        public static T[] Distinct<T>(IEnumerable<T> items)
        {
            if (items == null) throw new ArgumentNullException(nameof(items));
            var count = Count(items);
            var added = 0;
            var array = new T[count];

            var comparer = EqualityComparer<T>.Default;
            foreach (var item in items)
            {
                if (item == null) continue;

                var contains = false;
                foreach (var i in array)
                {
                    if (comparer.Equals(i, item))
                    {
                        contains = true;
                        break;
                    }
                }
                if (contains) continue;

                array[added] = item;
                added++;
            }

            if (added < count)
            {
                var temp = new T[added];
                System.Array.Copy(array, 0, temp, 0, added);
                array = temp;
            }

            return array;
        }

        /// <summary>清理集合，去除 NULL 值。</summary>
        public static T[] Vacuum<T>(this IEnumerable<T> items) => FindAll(items, x => x != null);

        /// <summary>获取可枚举集合的部分元素。</summary>
        /// <typeparam name="T">集合元素的类型。</typeparam>
        /// <param name="objects">原集合。</param>
        /// <param name="skip">在集合前段要跳过的元素数量。</param>
        /// <param name="count">要获取的元素数量，指定为负数时不限元素数量。</param>
        /// <param name="stuffer">填充器，获取范围超出原集合的部分，使用此方法填充元素；此函数默认返回 <typeparamref name="T"/> 的默认值。</param>
        /// <returns>数量符合 count 的数组。</returns>
        public static T[] Slice<T>(IEnumerable<T> objects, int skip = 0, int count = -1, Func<T> stuffer = null)
        {
            if (count == 0) return new T[0];

            var ab = new ArrayBuilder<T>();
            var added = 0;
            if (skip < 0)
            {
                var end = 0 - skip;
                for (var i = 0; i < end; i++)
                {
                    ab.Add(stuffer == null ? default : stuffer());
                    added++;
                    if (count > 0 && added == count) return ab.Export();
                }
            }

            if (objects != null)
            {
                var offset = 0;
                foreach (var item in objects)
                {
                    if (offset < skip)
                    {
                        offset++;
                        continue;
                    }
                    ab.Add(item);
                    added++;
                    offset++;
                    if (count > 0 && added == count) return ab.Export();
                }
            }

            while (added < count)
            {
                ab.Add(stuffer == null ? default : stuffer());
                added++;
            }

            return ab.Export();
        }

        /// <summary>在数组尾部增加元素，生成新数组，不修改原数组。</summary>
        /// <returns>增加元素后的新数组。</returns>
        public static T[] Push<T>(this T[] array, T item)
        {
            if (array == null) return new T[] { item };

            var length = array.Length;
            var newArray = new T[length + 1];
            if (length > 0) System.Array.Copy(array, 0, newArray, 0, length);
            newArray[length] = item;
            return newArray;
        }

        /// <summary>在数组尾部增加元素，生成新数组，不修改原数组。</summary>
        /// <returns>增加元素后的新数组。</returns>
        public static T[] Push<T>(this T[] array, T[] items)
        {
            if (array == null) return items ?? new T[0];
            if (items == null)
            {
                var result = new T[array.Length];
                array.CopyTo(result, 0);
                return result;
            }
            else
            {
                var length1 = array.Length;
                var length2 = items.Length;
                var result = new T[length1 + length2];
                if (length1 > 0) System.Array.Copy(array, 0, result, 0, length1);
                if (length2 > 0) System.Array.Copy(items, 0, result, length1, length2);
                return result;
            }
        }

        /// <summary>在数组头部增加元素，生成新数组，不修改原数组。</summary>
        /// <returns>增加元素后的新数组。</returns>
        public static T[] Unshift<T>(this T[] array, T item)
        {
            if (array == null) return new T[] { item };

            var length = array.Length;
            var newArray = new T[length + 1];
            newArray[0] = item;
            if (length > 0) System.Array.Copy(array, 0, newArray, 1, length);
            return newArray;
        }

        /// <summary>在数组头部增加元素，生成新数组，不修改原数组。</summary>
        /// <returns>增加元素后的新数组。</returns>
        public static T[] Unshift<T>(this T[] array, T[] items)
        {
            if (array == null) return items ?? new T[0];
            if (items == null)
            {
                var result = new T[array.Length];
                array.CopyTo(result, 0);
                return result;
            }
            else
            {
                var length1 = array.Length;
                var length2 = items.Length;
                var result = new T[length1 + length2];
                if (length2 > 0) System.Array.Copy(items, 0, result, 0, length2);
                if (length1 > 0) System.Array.Copy(array, 0, result, length2, length1);
                return result;
            }
        }

        #endregion

        #region 排序

        /// <summary>对列表中的元素排序。</summary>
        public static List<T> Sort<T>(List<T> list, Func<T, T, int> comparison)
        {
            if (list == null) return null;
            if (comparison == null) return list;
            list.Sort(new Comparison<T>(comparison));
            return list;
        }

        /// <summary>对数组排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static T[] Sort<T>(T[] array, Func<T, T, int> comparison)
        {
            if (array == null) return array;
            if (comparison == null) return array;
            System.Array.Sort(array, new Comparison<T>(comparison));
            return array;
        }

        /// <summary>获取集合中的第一个元素。可指定失败时的默认返回值。</summary>
        public static T First<T>(IEnumerable<T> collection, T failed = default(T))
        {
            if (collection == null) return failed;

            var array = collection as T[];
            if (array != null) return array.Length > 0 ? array[0] : failed;

            var list = collection as IList<T>;
            if (list != null) return list.Count > 0 ? list[0] : failed;

            foreach (var item in collection) return item;
            return failed;
        }

        /// <summary>获取集合中的最后一个元素。可指定失败时的默认返回值。</summary>
        public static T Last<T>(IEnumerable<T> collection, T failed = default(T))
        {
            if (collection == null) return failed;

            var array = collection as T[];
            if (array != null) return array.Length > 0 ? array[array.Length - 1] : failed;

            var list = collection as IList<T>;
            if (list != null) return list.Count > 0 ? list[list.Count - 1] : failed;

            var value = failed;
            foreach (var item in collection) value = item;
            return value;
        }

        /// <summary>对数组升序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static T[] Ascend<T>(T[] array) where T : IComparable<T>
        {
            if (array == null) return null;
            array.Sort((a, b) => a.CompareTo(b));
            return array;
        }

        /// <summary>对数组升序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static List<T> Ascend<T>(List<T> list) where T : IComparable<T>
        {
            if (list == null) return null;
            list.Sort((a, b) => a.CompareTo(b));
            return list;
        }

        /// <summary>对数组升序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static void Ascend<T, TProp>(T[] array, Func<T, TProp> func) where TProp : IComparable<TProp>
        {
            if (array != null && func != null) Sort(array, (a, b) => func(a).CompareTo(func(b)));
        }

        /// <summary>对数组降序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static T[] Descend<T>(T[] array) where T : IComparable<T>
        {
            if (array == null) return array;
            Sort(array, (a, b) => 0 - a.CompareTo(b));
            return array;
        }

        /// <summary>对数组降序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static List<T> Descend<T>(List<T> list) where T : IComparable<T>
        {
            if (list == null) return null;
            list.Sort((a, b) => -a.CompareTo(b));
            return list;
        }

        /// <summary>对数组降序排序。</summary>
        /// <exception cref="NullReferenceException"></exception>
        public static void Descend<T, TProp>(T[] array, Func<T, TProp> func) where TProp : IComparable<TProp>
        {
            if (array != null && func != null) Sort(array, (a, b) => 0 - func(a).CompareTo(func(b)));
        }

        /// <summary>对字典中的键排序。</summary>
        public static Dictionary<TKey, TValue> SortKey<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TKey, TKey, int> comparison)
        {
            if (dict == null) return null;
            if (comparison == null) return null;
            var list = new List<KeyValuePair<TKey, TValue>>(dict);
            list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Key, b.Key)));
            dict.Clear();
            foreach (var item in list) dict.Add(item.Key, item.Value);
            return dict;
        }

        /// <summary>对字典中的键排序。</summary>
        public static Dictionary<TKey, TValue> SortKey<TKey, TValue>(Dictionary<TKey, TValue> @this) where TKey : IComparable<TKey>
        {
            return SortKey(@this, (a, b) => a.CompareTo(b));
        }

        /// <summary>对字典中的值排序。</summary>
        public static Dictionary<TKey, TValue> SortValue<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TValue, TValue, int> comparison)
        {
            if (dict == null) return null;
            if (comparison == null) return dict;
            var list = new List<KeyValuePair<TKey, TValue>>(dict);
            list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Value, b.Value)));
            dict.Clear();
            foreach (var item in list) dict.Add(item.Key, item.Value);
            return dict;
        }

        /// <summary>对字典中的值排序。</summary>
        public static Dictionary<TKey, TValue> SortValue<TKey, TValue>(Dictionary<TKey, TValue> @this) where TValue : IComparable<TValue>
        {
            return SortValue(@this, (a, b) => a.CompareTo(b));
        }

        #endregion

        #region params

        internal static object[] ParseParams(object cells)
        {
            var parsed = new ArrayBuilder<object>();
            ParseParams(cells, parsed, 1);
            return parsed;
        }

        static void ParseParams(object cells, ArrayBuilder<object> parsed, int depth)
        {
            if (cells.IsNull()) return;

            if (cells is string str)
            {
                parsed.Add(cells);
                return;
            }

            if (cells is IList items)
            {
                if (depth > 64)
                {
                    parsed.Add(nameof(IList));
                    return;
                }
                var count = items.Count;
                for (var i = 0; i < count; i++)
                {
                    ParseParams(items[i], parsed, depth + 1);
                }
                return;
            }

            parsed.Add(cells.ToString());
        }

        #endregion

        #region Find

        /// <summary>根据条件筛选，将符合条件的元素组成新数组。</summary>
        public static T[] FindAll<T>(this IEnumerable<T> collection, Predicate<T> match)
        {
            if (collection == null) new ArgumentNullException(nameof(collection));
            if (match == null) throw new ArgumentNullException(nameof(match));

            if (collection is T[] array)
            {
                return System.Array.FindAll<T>(array, match);
            }
            else if (collection is IList<T> list)
            {
                var count = list.Count;
                var result = new List<T>(count);
                for (var i = 0; i < count; i++)
                {
                    var matched = match.Invoke(list[i]);
                    if (matched) result.Add(list[i]);
                }
                return result.ToArray();
            }
            else
            {
                var result = new List<T>();
                foreach (var item in collection)
                {
                    var matched = match.Invoke(item);
                    if (matched) result.Add(item);
                }
                return result.ToArray();
            }
        }

        /// <summary>根据条件筛选，找到第一个符合条件的元素。</summary>
        public static T Find<T>(this IEnumerable<T> collection, Predicate<T> match)
        {
            if (collection == null) throw new ArgumentNullException(nameof(collection));
            if (match == null) throw new ArgumentNullException(nameof(match));

            if (collection is T[] array)
            {
                return System.Array.Find<T>(array, match);
            }
            else if (collection is IList<T> list)
            {
                var count = list.Count;
                for (var i = 0; i < count; i++)
                {
                    var matched = match.Invoke(list[i]);
                    if (matched) return list[i];
                }
            }
            else
            {
                foreach (var item in collection)
                {
                    var matched = match.Invoke(item);
                    if (matched) return item;
                }
            }

            return default;
        }

        #endregion

        #region Map

        /// <summary>遍历集合，转换元素，生成新数组。</summary>
        /// <typeparam name="TIn">输入的元素类型。</typeparam>
        /// <typeparam name="TOut">输出的元素类型。</typeparam>
        /// <param name="collection">要遍历的集合。</param>
        /// <param name="selector">转换程序。</param>
        /// <returns>新数组的元素类型。</returns>
        public static TOut[] Map<TIn, TOut>(this IEnumerable<TIn> collection, Func<TIn, TOut> selector)
        {
            if (selector == null) throw new ArgumentNullException(nameof(selector));
            if (collection == null) return new TOut[0];

            return Map(collection, (item, index) => selector.Invoke(item));
        }

        /// <summary>遍历集合，转换元素，生成新数组。</summary>
        /// <typeparam name="TIn">输入的元素类型。</typeparam>
        /// <typeparam name="TOut">输出的元素类型。</typeparam>
        /// <param name="collection">要遍历的集合。</param>
        /// <param name="selector">转换程序，提供索引参数（从 0 开始）。</param>
        /// <returns>新数组的元素类型。</returns>
        public static TOut[] Map<TIn, TOut>(this IEnumerable<TIn> collection, Func<TIn, int, TOut> selector)
        {
            if (selector == null) throw new ArgumentNullException(nameof(selector));
            if (collection == null) return new TOut[0];

            if (collection is TIn[] array)
            {
                var count = array.Length;
                var result = new TOut[count];
                for (var i = 0; i < count; i++)
                {
                    result[i] = selector.Invoke(array[i], i);
                }
                return result;
            }
            else
            {
                var capacity = 0;
                var count = 0;
                var list = new List<TOut>();
                foreach (var item in collection)
                {
                    if (capacity == count)
                    {
                        capacity += 1024;
                        list.Capacity += capacity;
                    }
                    list.Add(selector.Invoke(item, count));
                    count += 1;
                }
                return list.ToArray();
            }
        }

        #endregion

        #region ForEach

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="callback">回调。参数为本次遍历的元素。</param>
        public static void ForEach<T>(this IEnumerable<T> collection, Action<T> callback)
        {
            if (collection == null || callback == null) return;
            ForEach<T>(collection, (item, index) =>
            {
                callback.Invoke(item);
                return JumpStatement.Continue;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="callback">回调。参数为本次遍历的元素和遍历的索引值，索引值从 0 开始。</param>
        public static void ForEach<T>(this IEnumerable<T> collection, Action<T, int> callback)
        {
            if (collection == null || callback == null) return;
            ForEach<T>(collection, (item, index) =>
            {
                callback.Invoke(item, index);
                return JumpStatement.Continue;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="callback">回调。参数为本次遍历的元素。</param>
        public static void ForEach<T>(this IEnumerable<T> collection, Func<T, JumpStatement> callback)
        {
            if (collection == null || callback == null) return;
            ForEach<T>(collection, (item, index) =>
            {
                var result = callback.Invoke(item);
                return result;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="callback">回调。参数为本次遍历的元素和遍历的索引值，索引值从 0 开始。返回 true 将继续遍历，返回 false 打断遍历。</param>
        public static void ForEach<T>(this IEnumerable<T> collection, Func<T, int, JumpStatement> callback)
        {
            if (collection == null || callback == null) return;

            if (collection is T[] array)
            {
                var count = array.Length;
                for (var i = 0; i < count; i++)
                {
                    var jump = callback.Invoke(array[i], i);
                    if (jump == JumpStatement.Break) break;
                }
            }
            else
            {
                var index = 0;
                foreach (var item in collection)
                {
                    var jump = callback.Invoke(item, index);
                    if (jump == JumpStatement.Break) break;
                    index += 1;
                }
            }
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="limit">每次遍历的元素数量。</param>
        /// <param name="callback">回调。参数为本次遍历的元素和遍历的索引值，索引值从 0 开始。</param>
        /// <exception cref="ArgumentOutOfRangeException" />
        public static void ForEach<T>(this IEnumerable<T> collection, int limit, Action<T[]> callback)
        {
            if (collection == null || callback == null) return;

            ForEach<T>(collection, limit, (items, index) =>
            {
                callback.Invoke(items);
                return JumpStatement.Continue;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="limit">每次遍历的元素数量。</param>
        /// <param name="callback">回调。参数为本次遍历的元素和遍历的索引值，索引值从 0 开始。</param>
        /// <exception cref="ArgumentOutOfRangeException" />
        public static void ForEach<T>(this IEnumerable<T> collection, int limit, Action<T[], int> callback)
        {
            if (collection == null || callback == null) return;

            ForEach<T>(collection, limit, (items, index) =>
            {
                callback.Invoke(items, index);
                return JumpStatement.Continue;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="limit">每次遍历的元素数量。</param>
        /// <param name="callback">回调。参数为本次遍历的元素。</param>
        /// <exception cref="ArgumentOutOfRangeException" />
        public static void ForEach<T>(this IEnumerable<T> collection, int limit, Func<T[], JumpStatement> callback)
        {
            if (collection == null || callback == null) return;

            ForEach<T>(collection, limit, (items, index) =>
            {
                var result = callback.Invoke(items);
                return result;
            });
        }

        /// <summary>遍历每个元素，执行回调。</summary>
        /// <typeparam name="T">元素的类型。</typeparam>
        /// <param name="collection">元素的集合。</param>
        /// <param name="limit">每次遍历的元素数量。</param>
        /// <param name="callback">回调。参数为本次遍历的元素和遍历的索引值，索引值从 0 开始。</param>
        /// <exception cref="ArgumentOutOfRangeException" />
        public static void ForEach<T>(this IEnumerable<T> collection, int limit, Func<T[], int, JumpStatement> callback)
        {
            if (limit < 1) throw new ArgumentOutOfRangeException(nameof(limit));
            if (collection == null) return;
            if (callback == null) return;

            if (collection is T[] array)
            {
                var total = array.LongLength;
                var start = 0L;
                var index = 0;
                var length = 0L;
                while (start < total)
                {
                    length = limit;
                    if (start + length > total) length = total - start;
                    var temp = new T[length];
                    System.Array.Copy(array, start, temp, 0L, length);
                    var jump = callback.Invoke(temp, index);
                    if (jump == JumpStatement.Break) break;

                    start += length;
                    index += 1;
                }
                return;
            }
            else
            {
                var queue = new Queue<T>(collection);
                var index = 0;
                while (queue.Count > 0)
                {
                    var list = new List<T>(limit);
                    while (list.Count < limit && queue.Count > 0) list.Add(queue.Dequeue());

                    var temp = list.ToArray();
                    var jump = callback.Invoke(temp, index);
                    if (jump == JumpStatement.Break) break;

                    index += 1;
                }
            }
        }

        #endregion

        #region Join

        /// <summary>连接多个集合的元素为单个集合。</summary>
        public static T[] Join<T>(params IEnumerable<T>[] collections)
        {
            if (collections == null) return new T[0];

            var count = collections.Length;
            if (count < 1) return new T[0];

            var result = new List<T>();
            foreach (var collection in collections)
            {
                if (collection == null) continue;
                foreach (var item in collection)
                {
                    result.Add(item);
                }
            }
            return result.ToArray();
        }

        #endregion

    }

}
